#include "stdint.h"
#include "stdio.h"
#include "string.h"
#include "DevicesCRC.h"
#include "DevicesSPIFlash.h"
#include "DriverFile.h"
#include "DriverFont.h"


int32_t utf2uni(void *pvIn, void*pvOut)
{
    uint32_t *pucUnicode = pvOut;
    uint8_t *pucUtf8 = pvIn;

    if(pucUtf8[0] < 0x80)
    {
        *pucUnicode = pucUtf8[0];
        return 1;
    }
    else if(pucUtf8[0] < 0xC0)
    {
        /* 编码解析有错误 */
        *pucUnicode = 0;
        return 1;
    }
    else if(pucUtf8[0] < 0xE0)
    {
        *pucUnicode = ((uint32_t)(pucUtf8[0] & 0x1F) << 6) | (pucUtf8[1] & 0x3F);
        return 2;
    }
    else if(pucUtf8[0] < 0xF0)
    {
        *pucUnicode = ((uint32_t)(pucUtf8[0] & 0x0F) << 12) | ((uint32_t)(pucUtf8[1] & 0x3F) << 6) | (pucUtf8[2] & 0x3F);
        return 3;
    }
    else
    {
        *pucUnicode = ((uint32_t)(pucUtf8[0] & 0x07) << 18) | ((uint32_t)(pucUtf8[1] & 0x3F) << 12) | ((uint32_t)(pucUtf8[2] & 0x3F) << 6) | (pucUtf8[3] & 0x3F);
        return 4;
    }
}

int32_t uni2utf(void *pvIn, void*pvOut)
{
    uint32_t *pucUnicode = pvIn;
    uint8_t *pucUtf8 = pvOut;

    if(*pucUnicode < 0x80)
    {
        *pucUtf8++ = *pucUnicode;
    }
    else if(*pucUnicode < 0x800)
    {
        *pucUtf8++ = 0xC0 | *pucUnicode >> 6;
        *pucUtf8++ = 0x80 | *pucUnicode & 0x3F;
    }
    else if(*pucUnicode < 0x10000)
    {
        *pucUtf8++ = 0xE0 |  *pucUnicode >> 12;
        *pucUtf8++ = 0x80 | (*pucUnicode >> 6) & 0x3F;
        *pucUtf8++ = 0x80 |  *pucUnicode & 0x3F;
    }
    else
    {
        *pucUtf8++ = 0xF0 |  *pucUnicode >> 18;
        *pucUtf8++ = 0x80 | (*pucUnicode >> 12) & 0x3F;
        *pucUtf8++ = 0x80 | (*pucUnicode >> 6 ) & 0x3F;
        *pucUtf8++ = 0x80 |  *pucUnicode & 0x3F;
    }

    return (uint32_t)pucUtf8 - (uint32_t)pvOut;
}

/* N*16 */
int32_t iFontUniLibrary16Get(uint32_t uiUnicode, void *pvBuff)
{
    const uint32_t uiASCIISize = 95 * 16;
    int32_t iSize = 0;

    if(pvBuff == NULL)
        return 0;

    /* ASCII */
    if((0x0020 <= uiUnicode) && (uiUnicode <= 0x007E))
    {
        uiUnicode = (uiUnicode - 0x0020) * 16;
        iSize = 16;
    }
    /* 基本汉字 */
    else if((0x4E00 <= uiUnicode) && (uiUnicode <= 0x9FA5))
    {
        uiUnicode = (uiUnicode - 0x4E00 + 0) * 32 + uiASCIISize;
        iSize = 32;
    }
    /* 基本汉字补充 */
    else if((0x9FA6 <= uiUnicode) && (uiUnicode <= 0x9FD5))
    {
        uiUnicode = (uiUnicode - 0x9FA6 + 20902) * 32 + uiASCIISize;
        iSize = 32;
    }
    /* 扩展A */
    else if((0x3400 <= uiUnicode) && (uiUnicode <= 0x4DB5))
    {
        uiUnicode = (uiUnicode - 0x3400 + 20950) * 32 + uiASCIISize;
        iSize = 32;
    }
    /* 兼容汉字 */
    else if((0xF900 <= uiUnicode) && (uiUnicode <= 0xFAD9))
    {
        uiUnicode = (uiUnicode - 0xF900 + 27532) * 32 + uiASCIISize;
        iSize = 32;
    }
    /* CJK标点符号 */
    else if((0x3000 <= uiUnicode) && (uiUnicode <= 0x303F))
    {
        uiUnicode = (uiUnicode - 0x3000 + 28006) * 32 + uiASCIISize;
        iSize = 32;
    }
    /* 半角及全角字符 */
    else if((0xFF00 <= uiUnicode) && (uiUnicode <= 0xFFEE))
    {
        uiUnicode = (uiUnicode - 0xFF00 + 28070) * 32 + uiASCIISize;
        iSize = 32;
    }
    /* CJK纵向标点符号 */
    else if((0xFE10 <= uiUnicode) && (uiUnicode <= 0xFE19))
    {
        uiUnicode = (uiUnicode - 0xFE10 + 28309) * 32 + uiASCIISize;
        iSize = 32;
    }
    /* CJK纵向标点符号 */
    else if((0xFE30 <= uiUnicode) && (uiUnicode <= 0xFE4F))
    {
        uiUnicode = (uiUnicode - 0xFE30 + 28319) * 32 + uiASCIISize;
        iSize = 32;
    }
    /* CJK特殊符号(月份, 日期) */
    else if((0x3200 <= uiUnicode) && (uiUnicode <= 0x33FF))
    {
        uiUnicode = (uiUnicode - 0x3200 + 28351) * 32 + uiASCIISize;
        iSize = 32;
    }
    /* 汉字笔画 */
    else if((0x31C0 <= uiUnicode) && (uiUnicode <= 0x31E3))
    {
        uiUnicode = (uiUnicode - 0x31C0 + 28863) * 32 + uiASCIISize;
        iSize = 32;
    }
    /* 康熙部首 */
    else if((0x2F00 <= uiUnicode) && (uiUnicode <= 0x2FD5))
    {
        uiUnicode = (uiUnicode - 0x2F00 + 28899) * 32 + uiASCIISize;
        iSize = 32;
    }

    /* 读取字模 */
    cSPIFlashReadDatas(SPI_FLASH_FONT_ADDR + uiUnicode, pvBuff, iSize);

    /* unicode ASCII编码部分每个字符占16Byte、中文编码部分每个字符占32Byte  */
    return iSize;
}

int8_t cFontInit(void)
{
#define FONT_PATH "./FONT/FONT.BIN"
#define FONT_PATH_RENAME "./FONT/FONT.BIN.BACK"

    uint32_t uiAddr;
    int32_t iFileSize, iSize, iLength;
    uint16_t usCrcFile, usCrc = 0xFFFF;
    uint8_t ucBuff[512];

    /* 把SD卡的字库文件，复制到SPI Flash，以给后续字库查询加速 */
    if(((iFileSize = iFileSizeGet(FONT_PATH)) > 0) && (iFileSize < 1024 * 1024))
    {
        usCrcFile = uiFileCrcGet(FONT_PATH);

        for(uiAddr = 0, iSize = iFileSize; iSize > 0; iSize -= sizeof(ucBuff))
        {
            iLength = iSize > sizeof(ucBuff) ? sizeof(ucBuff) : iSize;

            cSPIFlashReadDatas(SPI_FLASH_FONT_ADDR + uiAddr, ucBuff, iLength);
            usCrc = usCRC16_MODBUS(&usCrc, ucBuff, iLength);

            uiAddr += sizeof(ucBuff);
        }

        printf("cFontInit crc: %08X - %08X\r\n", usCrc, usCrcFile);

        /* 需要更新字库 */
        if(usCrc != usCrcFile)
        {
            for(uiAddr = 0, iSize = iFileSize; iSize > 0; iSize -= sizeof(ucBuff))
            {
                iLength = iSize > sizeof(ucBuff) ? sizeof(ucBuff) : iSize;

                cFileRead(FONT_PATH, uiAddr, ucBuff, iLength);
                cSPIFlashWriteDatas(SPI_FLASH_FONT_ADDR + uiAddr, ucBuff, iLength);

                uiAddr += sizeof(ucBuff);
            }
        }

        /* 重命名文件，以避免每次开机都进行读取 */
        cFileRename(FONT_PATH, FONT_PATH_RENAME);
    }

    return 0;
}
